package com.sunyard.manage.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.page.PageMethod;
import com.sunyard.constant.ErrMessageConst;
import com.sunyard.dal.bo.*;
import com.sunyard.dal.bo.finger.*;
import com.sunyard.dal.dto.DownloadFingerResDTO;
import com.sunyard.dal.dto.FingerCopyQueryResDTO;
import com.sunyard.dal.dto.OpFingerResDTO;
import com.sunyard.dal.dto.OtherParamDTO;
import com.sunyard.dal.entity.*;
import com.sunyard.dal.mapper.FingerCopyMapper;
import com.sunyard.dal.mapper.FingerMapper;
import com.sunyard.dal.mapper.OperatorMapper;
import com.sunyard.dal.mapper.OtherParamMapper;
import com.sunyard.enums.IsCheckEnum;
import com.sunyard.enums.OperatorFingerEnum;
import com.sunyard.manage.constant.TblLogConst;
import com.sunyard.manage.service.FingerService;
import com.sunyard.manage.service.OperatorLogService;
import com.sunyard.manage.service.OrganizationService;
import com.sunyard.utils.DateUtil;
import com.sunyard.utils.ExcelOutput;
import com.sunyard.utils.Response.BaseResult;
import com.sunyard.utils.Response.GetResult;
import com.sunyard.utils.Response.HeaderResult;
import com.sunyard.utils.TokenUtil;
import com.sunyard.utils.manage.DataGrid;
import com.sunyard.utils.manage.PageQuery;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

@Slf4j
@Service
public class FingerServiceImpl implements FingerService {

    @Autowired
    private FingerMapper fingerMapper;

    @Autowired
    private FingerCopyMapper fingerCopyMapper;

    @Autowired
    private OperatorMapper operatorMapper;

    @Autowired
    private OperatorLogService operatorLogService;

    @Autowired
    private OrganizationService organizationService;

    @Autowired
    private OtherParamMapper otherParamMapper;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult addFigner(FingerAddBO addBO, HttpServletRequest request) {
        String opId = TokenUtil.getOpId(request.getHeader("token"));
        String orgId = TokenUtil.getOrgId(request.getHeader("token"));
        String opName = TokenUtil.getOpName(request.getHeader("token"));

        List<String> list = new ArrayList<>();
        list.add(OtherParam.FINGER_ADD_AUTH);
        List<OtherParamDTO> otherParams = otherParamMapper.queryByKeys(list);
        if (!CollectionUtils.isEmpty(otherParams)){
            OtherParam otherParam = otherParams.get(0);
            if ("0".equals(otherParam.getConfValue()) ) {
                addBO.setAuditType("1");
                addBO.setAuditor(opId);
            }
        }
        //定义日志信息
        String logName = TblLogConst.FINGER_ADD;
        Operator operator = operatorMapper.getOperatorByOpId(addBO.getOpId());
        if (ObjectUtil.isNull(operator)) {
            return GetResult.getResultFail("该人员信息不存在");
        }
        //审核类型 1-同步审核 2-异步审核
        String isCheck = "1";
        if ("2".equals(addBO.getAuditType())) {
            isCheck = "0";
        }
        Finger fingerByType = fingerMapper.getFingerByType(String.valueOf(operator.getId()), addBO.getFingerType());
        if (ObjectUtil.isNotNull(fingerByType)) {
            fingerMapper.deleteByPrimaryKey(fingerByType.getId());
        }
        FingerCopy fingerCopy = fingerCopyMapper.getFingerByType(String.valueOf(operator.getId()), addBO.getFingerType());
        if (ObjectUtil.isNotNull(fingerCopy)) {
            return GetResult.getResultFail("该人员已录入该类型的指纹，待审核中");
        }
        Finger finger = new Finger();
        BeanUtil.copyProperties(addBO, finger);
        finger.setType(addBO.getFingerType());
        finger.setCreateTime(new Date());
        finger.setCreateUser(opId);
        finger.setOpId(String.valueOf(operator.getId()));
        Integer fignerId = null;
        //如果为审核通过，则将信息添加到信息表中
        if (IsCheckEnum.PASS_CHECKED.getCode().equals(isCheck)) {
            fingerMapper.insert(finger);
            fignerId = fingerMapper.getLastId();
            finger.setId(fignerId);
        }
        //添加审核信息
        addFingerCopy(finger, isCheck, addBO.getAuditor(), "1");
        String operationDesc = "用户" + opName + "对用户" + operator.getOpName() + "进行指纹录入";
        operatorLogService.insert(operationDesc, logName, "1", opId, opName, orgId);
        if (IsCheckEnum.PASS_CHECKED.getCode().equals(isCheck)) {
            return GetResult.getResultSuccess("录入成功");
        }
        return GetResult.getResultSuccess("录入成功,待审核");
    }

    @Override
    public BaseResult<List<OpFingerResDTO>> getOpFigner(OpFingerReqBO reqBO, HttpServletRequest request) {
        List<Finger> fingerList = fingerMapper.getFingerByOpId(reqBO.getOpId());
        List<OpFingerResDTO> resList = new ArrayList<>();
        for (Finger finger : fingerList) {
            OpFingerResDTO resDTO = new OpFingerResDTO();
            BeanUtil.copyProperties(finger, resDTO);
            resDTO.setFingerType(finger.getType());
            //指纹类型 1一号指纹 2二号指纹 3三号指纹
            if ("1".equals(finger.getType())) {
                resDTO.setFingerTypeName("一号指纹");
            } else if ("2".equals(finger.getType())) {
                resDTO.setFingerTypeName("二号指纹");
            } else {
                resDTO.setFingerTypeName("三号指纹");
            }
            resList.add(resDTO);
        }
        return GetResult.getResult(resList);
    }

    @Override
    public BaseResult deleteOpFinger(FingerDeleteBO deleteBO, HttpServletRequest request) {
        String opId = TokenUtil.getOpId(request.getHeader("token"));
        String orgId = TokenUtil.getOrgId(request.getHeader("token"));
        String opName = TokenUtil.getOpName(request.getHeader("token"));
        //定义日志信息
        String logName = TblLogConst.FINGER_DELETE;
        FingerVo fingerVo = fingerMapper.selectById(Integer.valueOf(deleteBO.getId()));
        String operationDesc = "用户" + opName + "删除用户" + fingerVo.getOpName() + "的指纹，指纹位置为：" + OperatorFingerEnum.getValue(fingerVo.getType());
        //审核类型 1-同步审核 2-异步审核
        String isCheck = "0";
        if ("1".equals(deleteBO.getAuditType())) {
            isCheck = "1";
        }
        Finger finger = fingerMapper.selectByPrimaryKey(Integer.valueOf(deleteBO.getId()));
        if (ObjectUtil.isNull(finger)) {
            return GetResult.getResultFail("未查询到指纹信息，请核对");
        }
        int count = fingerCopyMapper.getCopyCount(finger.getId());
        if (count > 0) {
            return GetResult.getResultFail("该指纹存在未审核信息，无法删除");
        }
        if (IsCheckEnum.PASS_CHECKED.getCode().equals(isCheck)) {
            fingerMapper.deleteByPrimaryKey(Integer.valueOf(deleteBO.getId()));
        }
        //添加审核信息
        addFingerCopy(finger, isCheck, deleteBO.getAuditor(), "2");
        operatorLogService.insert(operationDesc, logName, "1", opId, opName, orgId);
        return GetResult.getResultSuccess("操作成功");
    }

    @Override
    public BaseResult<DataGrid<FingerCopyQueryResDTO>> getFingerCopyByPage(PaginationBO<FingerCopyQueryBO> queryBO, HttpServletRequest request) throws Exception {
        FingerCopyQueryBO copyQueryBO = queryBO.getParams();
        log.info("终端信息查询入参：{}", JSON.toJSONString(copyQueryBO));
        String orgId = TokenUtil.getOrgId(request.getHeader("token"));
        if (StringUtils.isBlank(copyQueryBO.getOrgId())) {
            String org = getOrgIdAllChild(orgId);
            copyQueryBO.setOrgId(org);
        }
        //设置分页信息
        PageMethod.startPage(queryBO.getPageNo(), queryBO.getPageSize());
        List<FingerCopy> fingerCopyList = fingerCopyMapper.getFingerCopyByPage(copyQueryBO);
        List<FingerCopyQueryResDTO> resList = new ArrayList<>();
        for (FingerCopy fingerCopy : fingerCopyList) {
            FingerCopyQueryResDTO resDTO = new FingerCopyQueryResDTO();
            BeanUtil.copyProperties(fingerCopy, resDTO);
            resDTO.setAuditId(fingerCopy.getId());
            resDTO.setFingerType(fingerCopy.getType());
            resDTO.setAuditFlag(fingerCopy.getIsCheck());
            resDTO.setCreateTime(DateUtil.getDateStr(DateUtil.YYYYMMDD_HHMMSS, fingerCopy.getCreateTime()));
            Operator operator = operatorMapper.getOperatorByOpId(fingerCopy.getCreateUser());
            if (ObjectUtil.isNotNull(operator)) {
                resDTO.setCreateUser(operator.getOpName());
            }
            operator = operatorMapper.getOperatorById(fingerCopy.getOpId());
            if (ObjectUtil.isNotNull(operator)) {
                resDTO.setOpName(operator.getOpName());
            }
            resList.add(resDTO);
        }
        DataGrid dataGrid = PageQuery.getDataGrids(fingerCopyList, resList);
        return GetResult.getResult(dataGrid);
    }

    @Override
    public void fingerAuditExport(HttpServletResponse response, FingerCopyQueryBO fingerCopyQueryBO, HttpServletRequest request) {
        try {
            String opId = TokenUtil.getOpId(request.getHeader("token"));
            String orgId = TokenUtil.getOrgId(request.getHeader("token"));
            String opName = TokenUtil.getOpName(request.getHeader("token"));
            operatorLogService.insert("指纹审核导出", "指纹审核导出", "1", opId, opName, orgId);
            if (StringUtils.isBlank(fingerCopyQueryBO.getOrgId())) {
                String org = getOrgIdAllChild(orgId);
                fingerCopyQueryBO.setOrgId(org);
            }
            // 执行查询
            List<FingerCopyExport> list = fingerCopyMapper.fingerAuditExport(fingerCopyQueryBO);
            if (list == null || list.isEmpty()) {
                throw new RuntimeException("无数据无需导出");
            }
            String title = "指纹审核导出" + ".xls";
            String[] headers = new String[]{"用户编号", "用户名称", "指纹类型", "审核人", "审核类型", "创建时间","创建人", "审核状态"};

            List<Object[]> dataList;
            dataList = list.stream().map(roleCopy -> {
                Object[] obj = new Object[headers.length];
                obj[0] = roleCopy.getOpId();
                obj[1] = roleCopy.getOpName();
                obj[2] = roleCopy.getType();
                obj[3] = roleCopy.getCheckOpName();
                obj[4] = roleCopy.getAuditType();
                obj[5] = roleCopy.getCreateTime();
                obj[6] = roleCopy.getCreateUserName();
                obj[7] = roleCopy.getIsCheck();
                return obj;
            }).collect(toList());
            OutputStream out = null;
            // 防止中文乱码
            String headStr = "attachment; filename=\"" + new String(title.getBytes("gb2312"), "ISO8859-1") + "\"";
            response.setContentType("octets/stream");
            response.setContentType("APPLICATION/OCTET-STREAM");
            response.setHeader("Content-Disposition", headStr);
            out = response.getOutputStream();
            ExcelOutput ex = new ExcelOutput(title, headers, dataList);
            ex.export(out);
            log.info("指纹审核导出");
        } catch (Exception e) {
            log.error(ErrMessageConst.SYSTEM_ERROR, e);
            HeaderResult.setFailHeader(request, response, e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult auditFinger(FingerAuditBO auditBO, HttpServletRequest request) {
        String opId = TokenUtil.getOpId(request.getHeader("token"));
        String orgId = TokenUtil.getOrgId(request.getHeader("token"));
        String opName = TokenUtil.getOpName(request.getHeader("token"));
        //定义日志信息
        String logName = TblLogConst.FINGER_AUDIT;
        FingerCopyVo fingerCopyVo = fingerCopyMapper.selectById(Integer.valueOf(auditBO.getAuditId()));
        String operationDesc = "用户" + opName + "对用户" +fingerCopyVo.getOpName() + "进行指纹审核，指纹位置为：" + OperatorFingerEnum.getValue(fingerCopyVo.getType());
        FingerCopy fingerCopy = fingerCopyMapper.selectByPrimaryKey(Integer.valueOf(auditBO.getAuditId()));
        if (ObjectUtil.isNull(fingerCopy)) {
            return GetResult.getResultFail("未查询到审核信息，请核对");
        }
        if (!fingerCopy.getCheckOpId().equals(opId)) {
            return GetResult.getResultFail("您没有审核该信息的权限");
        }
        //如果为指纹录入审核，则直接将数据添加到信息表
        if ("1".equals(fingerCopy.getAuditType())
                && IsCheckEnum.PASS_CHECKED.getCode().equals(auditBO.getAuditFlag())) {
            Finger finger = new Finger();
            finger.setOpId(fingerCopy.getOpId());
            finger.setType(fingerCopy.getType());
            finger.setFinger(fingerCopy.getFinger());
            finger.setFirm(fingerCopy.getFirm());
            finger.setCreateTime(new Date());
            finger.setCreateUser(fingerCopy.getCreateUser());
            fingerMapper.insert(finger);
        } else if ("2".equals(fingerCopy.getAuditType())
                && IsCheckEnum.PASS_CHECKED.getCode().equals(auditBO.getAuditFlag())) {
            //如果为删除审核，则直接删除信息表数据
            fingerMapper.deleteByPrimaryKey(fingerCopy.getFingerId());
        }
        fingerCopy.setIsCheck(auditBO.getAuditFlag());
        fingerCopy.setAuditDesc(auditBO.getAuditDesc());
        fingerCopyMapper.updateByPrimaryKey(fingerCopy);
        operatorLogService.insert(operationDesc, logName, "1", opId, opName, orgId);
        return GetResult.getResultSuccess("操作成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult batchAuditFinger(FingerAuditBO auditBO, HttpServletRequest request) {
        String[] auditIds = auditBO.getAuditId().split(",");
        for (String auditId : auditIds) {
            FingerAuditBO fingerAuditBO = new FingerAuditBO();
            BeanUtil.copyProperties(auditBO, fingerAuditBO);
            fingerAuditBO.setAuditId(auditId);
            BaseResult result = auditFinger(fingerAuditBO, request);
            if (!"00".equals(result.getDataCode())) {
                return GetResult.getResultFail(result.getDataMessage());
            }
        }
        return GetResult.getResultSuccess("审核成功");
    }

    @Override
    public BaseResult<List<DownloadFingerResDTO>> batchDownloadFigner(OpFingerReqBO reqBO, HttpServletRequest request) {
        String opId = TokenUtil.getOpId(request.getHeader("token"));
        String orgId = TokenUtil.getOrgId(request.getHeader("token"));
        String opName = TokenUtil.getOpName(request.getHeader("token"));
        String[] opIds = reqBO.getOpId().split(",");
        String logName = "批量指纹下载";
        String operationDesc = "用户" + opName + "进行批量指纹下载";
        List<Finger> list = fingerMapper.getBatchFingerByOpId(opIds);
        List<DownloadFingerResDTO> resList = new ArrayList<>();
        if (list.size() <= 0) {
            return GetResult.getResultFail("所选人员无指纹数据");
        }
        for (Finger finger : list) {
            DownloadFingerResDTO resDTO = new DownloadFingerResDTO();
            resDTO.setTemplateData(finger.getFinger());
            resDTO.setFirm(finger.getFirm());
            Operator operator = operatorMapper.getOperatorById(finger.getOpId());
            if(null==operator){
                log.error("id,{},用户不存在，下载指纹失败",finger.getOpId());
                return GetResult.getResultFail("用户(id="+finger.getOpId()+")不存在，下载指纹失败");
            }
            resDTO.setTellerInformation(Integer.valueOf(finger.getOpId()));
            resDTO.setFinger(Integer.parseInt(finger.getType()));
            resList.add(resDTO);
        }
        operatorLogService.insert(operationDesc, logName, "1", opId, opName, orgId);
        return GetResult.getResult(resList);
    }

    @Override
    public BaseResult<List<DownloadFingerResDTO>> downloadFigner(OpFingerReqBO reqBO, HttpServletRequest request) {
        String opId = TokenUtil.getOpId(request.getHeader("token"));
        String orgId = TokenUtil.getOrgId(request.getHeader("token"));
        String opName = TokenUtil.getOpName(request.getHeader("token"));
        //定义日志信息
        String logName = TblLogConst.FINGER_DOWNLOAD;
        String operationDesc = "用户" + opName + "进行指纹下载";
        List<Finger> list = fingerMapper.getFingerByOpId(reqBO.getOpId());
        List<DownloadFingerResDTO> resList = new ArrayList<>();
        if (list.size() <= 0) {
            return GetResult.getResultFail("该人员无指纹数据");
        }
        for (Finger finger : list) {
            Operator operator = operatorMapper.getOperatorById(finger.getOpId());
            if(null==operator){
                log.error("id,{},用户不存在，下载指纹失败",finger.getOpId());
                return GetResult.getResultFail("用户(id="+finger.getOpId()+")不存在，下载指纹失败");
            }
            DownloadFingerResDTO resDTO = new DownloadFingerResDTO();
            resDTO.setTemplateData(finger.getFinger());
            resDTO.setFirm(finger.getFirm());
            resDTO.setTellerInformation(Integer.valueOf(finger.getOpId()));
            resDTO.setFinger(Integer.parseInt(finger.getType()));
            resList.add(resDTO);
        }
        operatorLogService.insert(operationDesc, logName, "1", opId, opName, orgId);
        return GetResult.getResult(resList);
    }

    public String getOrgIdAllChild(String orgId) throws Exception {
        List<Organization> orgList = organizationService.getOrgIds(orgId);
        StringBuilder sb = new StringBuilder();
        for (Organization organization : orgList) {
            sb.append(organization.getOrgId()).append(",");
        }
        int size = sb.toString().length() - 1;
        return sb.toString().substring(0, size);
    }

    /**
     * 添加审核信息
     *
     * @param finger    终端信息
     * @param isCheck   审核状态 0未审核 1审核通过
     * @param checkOpId 申请复核人，不限制时填0
     **/
    @Transactional(rollbackFor = Exception.class)
    public void addFingerCopy(Finger finger, String isCheck, String checkOpId, String auditType) {
        //查询该终端是否存在添加审核
        FingerCopy fingerCopy = fingerCopyMapper.selectByFingerId(finger.getId(), finger.getType());
        if (ObjectUtil.isNull(fingerCopy)) {
            fingerCopy = new FingerCopy();
        }
        fingerCopy.setType(finger.getType());
        fingerCopy.setOpId(finger.getOpId());
        fingerCopy.setFingerId(finger.getId());
        fingerCopy.setFinger(finger.getFinger());
        fingerCopy.setFirm(finger.getFirm());
        fingerCopy.setCreateTime(new Date());
        fingerCopy.setCreateUser(finger.getCreateUser());
        fingerCopy.setAuditType(auditType);
        fingerCopy.setIsCheck(isCheck);
        fingerCopy.setCheckOpId(checkOpId);
        if (fingerCopy.getId() != null) {
            fingerCopyMapper.updateByPrimaryKey(fingerCopy);
        } else {
            fingerCopyMapper.insert(fingerCopy);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult fingerConvert() {
        List<Operator> operators = operatorMapper.getOperators();
        Map<String, Integer> map = operators.stream().collect(Collectors.toMap(Operator::getOpId, Operator::getId, (key1, key2) -> key2));
        List<Finger> fingers = fingerMapper.getFingers();
        List<Finger> updateFingers = new ArrayList<>();
        for (Finger finger : fingers) {
            Integer integer = map.get(finger.getOpId());
            if (null != integer){
                Finger finger1 = new Finger();
                BeanUtil.copyProperties(finger,finger1);
                finger1.setOpId(String.valueOf(integer));
                updateFingers.add(finger1);
            }

        }
        for (Finger updateFinger : updateFingers) {
            fingerMapper.updateByPrimaryKey(updateFinger);
        }

        return GetResult.getResultSuccess("修改成功");
    }
}
